home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 7
/
Aminet 7 - August 1995.iso
/
Aminet
/
comm
/
tcp
/
AmigaTCP.lha
/
AmigaTCP
/
src
/
newtelnetp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-24
|
15KB
|
742 lines
#include <stdio.h>
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/tasks.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/io.h>
#include <exec/devices.h>
#include <exec/errors.h>
#include <proto/exec.h>
#include <devices/console.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <dos.h>
#include "machdep.h"
#include "mbuf.h"
#include "timer.h"
#include "internet.h"
#include "icmp.h"
#include "netuser.h"
#include "tcp.h"
#include "telnet.h"
#include "session.h"
#include "inetdev.h"
#include "inetlib.h"
#define DEBUG
struct Process *mytask;
APTR oldwindowptr;
struct IntuitionBase *IntuitionBase;
char banner[80] = "telnet window";
static struct NewWindow nw = {
0, 0, 640, 200, /* left, top, (max) width, (max) height */
0, 1, /* detail pen, block pen */
0, /* IDCMP flags */
SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING |
SIZEBBOTTOM | ACTIVATE | NOCAREREFRESH, /* window flags */
NULL, NULL, /* gadget, checkmark */
(UBYTE *)&banner[0], /* title of window */
NULL, NULL, /* screen, bitmap */
200, 50, -1, -1, /* sizing limits */
WBENCHSCREEN, /* on the workbench */
};
struct Window *win;
struct MsgPort *keyboard, *consinp, *consoutp, *tcpinp, *tcpoutp;
struct IOStdReq consin, consout;
char InputCharacter;
int deviceopened = 0;
struct IOINETReq tnreq, tninreq, tnoutreq;
char recv[512], snd[512], recvbuf[512], tcpinbuf[512];
struct telnet *tn;
#ifdef LATTICE
extern struct { short error; char *msg; } os_errlist[];
extern int _OSERR, os_nerr;
#endif
static
/*
* wait for something to happen
*/
eihalt()
{
register struct IntuiMessage *msg;
static ULONG mask = 0;
if (mask == 0L)
mask = 1L << consinp->mp_SigBit |
1L << tcpinp->mp_SigBit;
(void) Wait(mask);
}
clean(why)
char *why;
{
int i;
if (win)
CloseWindow(win);
if (consinp)
DeletePort(consinp);
if (consoutp)
DeletePort(consoutp);
if (tcpinp)
DeletePort(tcpinp);
if (tcpoutp)
DeletePort(tcpoutp);
if (deviceopened)
CloseDevice(&tnreq);
mytask->pr_WindowPtr = oldwindowptr;
if (why) {
myoserr(why);
}
exit(0);
}
printlist(l)
struct List *l;
{
printf("head %x tail %x tailpred %x\n", l->lh_Head, l->lh_Tail,
l->lh_TailPred);
}
myoserr(why)
char *why;
{
int i;
fprintf(stderr, "%s: ", why);
#ifdef LATTICE
fprintf(stderr, "%d: ", _OSERR);
for(i = 0; os_errlist[i].error < os_nerr; i++)
if (os_errlist[i].error == _OSERR)
fprintf(stderr, os_errlist[i].msg);
#endif
fprintf(stderr, "\r\n");
}
/* Called at startup time to set up console I/O, memory heap */
ioinit()
{
struct Screen *scr;
mytask = (struct Process *) FindTask((char *) NULL);
oldwindowptr = mytask->pr_WindowPtr;
mytask->pr_WindowPtr = (APTR) -1; /* disable DOS requestors */
if ((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 33L)) == NULL)
clean("No intuition: Version 1.2 of Amiga Systems Software required");
/*
* Try to determine the size of the workbench screen
*/
scr = malloc(sizeof(struct Screen));
if (scr==NULL)
clean("Can't alloc screen");
if (GetScreenData(scr, (ULONG) sizeof(struct Screen),
WBENCHSCREEN, NULL) == TRUE) {
nw.Width = scr->Width;
nw.Height = scr->Height-20;
nw.TopEdge = 19;
} else
fprintf(stderr, "Can't GetScreenData()\n");
free((char *)scr);
if ((win = OpenWindow(&nw)) == NULL)
clean("Can't open window");
if ((consinp = CreatePort("telnet:console in", 0L)) == NULL)
clean("Can't create console port");
if ((tcpinp = CreatePort("telnet:tcp in", 0L)) == NULL)
clean("Can't create telnet tcp input port");
if ((tcpoutp = CreatePort("telnet:tcp out", 0L)) == NULL)
clean("Can't create telnet tcp output port");
consin.io_Data = (APTR) win;
consin.io_Length = sizeof(struct Window);
_OSERR = OpenDevice("console.device", 0L, &consin, 0L);
if (_OSERR != 0L){
printf("opendevice returned %d\n", _OSERR);
myoserr("could not get console");
clean("Can't open console device");
}
consout = consin;
consin.io_Message.mn_ReplyPort = consinp;
consin.io_Length = 512;
consin.io_Data = (APTR) recvbuf;
consin.io_Command = CMD_READ;
SendIO(&consin);
consout.io_Message.mn_ReplyPort = consoutp;
consout.io_Command = CMD_WRITE;
}
/* Read characters from the keyboard, translating them to "real" ASCII
* If none are ready, return the -1 from kbraw()
*/
kbread()
{
char c;
int amount;
if (CheckIO(&consin)) {
WaitIO(&consin);
amount = consin.io_Actual;
if (amount > 512)
amount = 511;
strncpy(recv, recvbuf, amount);
SendIO(&consin);
return (amount);
}
return -1; /* nuthin here */
}
extern char nospace[];
int refuse_echo = 0;
int unix_line_mode = 0; /* if true turn <cr> to <nl> when in line mode */
#ifdef DEBUG
char *t_options[] = {
"Transmit Binary",
"Echo",
"",
"Suppress Go Ahead",
"",
"Status",
"Timing Mark"
};
#endif
/* Telnet receiver upcall routine */
void
rcv_char()
{
tel_input(tn,tninreq.io_Data, tninreq.io_Actual);
fflush(stdout);
}
brk()
{
clean("ok i iwll quit\n");
}
/* TCP connection states */
char *tcpstates[] = {
"Closed",
"Listen",
"SYN sent",
"SYN received",
"Established",
"FIN wait 1",
"FIN wait 2",
"Close wait",
"Closing",
"Last ACK",
"Time wait"
};
/* TCP segment header flags */
char *tcpflags[] = {
"FIN", /* 0x01 */
"SYN", /* 0x02 */
"RST", /* 0x04 */
"PSH", /* 0x08 */
"ACK", /* 0x10 */
"URG" /* 0x20 */
};
/* TCP closing reasons */
char *reasons[] = {
"Normal",
"Reset",
"Timeout",
"ICMP"
};
char old = LISTEN;
int done = 0;
char *hostname="";
int hostport=0;
char *bannerfmt = "telnet %10s %4d %10s";
void
showstate(old, new)
char old, new;
{
/* Can't add a check for unknown connection here, it would loop
* on a close upcall! We're just careful later on.
*/
sprintf(banner, bannerfmt, hostname, hostport, tcpstates[new]);
SetWindowTitles(win, banner, -1);
switch(new){
case CLOSE_WAIT:
done = 1;
break;
case CLOSED: /* court adjourned */
done = 1;
break;
default:
break;
}
fflush(stdout);
}
/* Execute user telnet command */
main(argc,argv)
int argc;
char *argv[];
{
extern int _OSERR;
struct InternetBase *InternetBase;
int send_tel();
int unix_send_tel();
struct session *s;
int amount;
struct socket lsocket,fsocket;
ioinit();
hostname = argv[1];
old = LISTEN;
showstate(old, LISTEN);
tnreq.io_fsocket.address = aton(argv[1]);
if(argc < 3)
tnreq.io_fsocket.port = TELNET_PORT;
else
tnreq.io_fsocket.port = atoi(argv[2]);
tnreq.io_Device = NULL;
tnreq.io_Unit = NULL;
tnreq.io_Flags = 0;
tnreq.io_Error = 0;
InternetBase = (struct InternetBase *) OpenDevice("internet.device",
(long) INET_UNIT_TCP, &tnreq, 0L);
if (InternetBase != 0L){
printf("it did not open %d\n",InternetBase);
clean("i quit");
}
hostport = tnreq.io_lsocket.port;
deviceopened = 1;
tninreq = tnreq; /* possible lettuce bug ?*/
tnoutreq = tnreq;
tninreq.io_Length = 512;
tnoutreq.io_Length = 1;
tninreq.io_Data = tcpinbuf;
tnoutreq.io_Data = snd;
tnoutreq.io_Length = 0;
tninreq.io_Command = CMD_READ;
tnoutreq.io_Command = CMD_WRITE;
tninreq.io_Message.mn_ReplyPort = tcpinp;
tnoutreq.io_Message.mn_ReplyPort = tcpoutp;
/* Create and initialize a Telnet protocol descriptor */
if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
myoserr("calloc faiuled\n");
goto done;
}
tn->session = s; /* Upward pointer */
tn->state = TS_DATA;
SendIO(&tninreq);
onbreak(&brk);
InputCharacter = ' ';
while (! done)
{
eihalt();
if ((amount = kbread()) >= 0){
unix_send_tel(recv, amount);}
if (CheckIO(&tninreq))
{
chkabort();
WaitIO(&tninreq);
rcv_char();
if (tninreq.io_State != old)
{
showstate(old, tninreq.io_State);
old = tninreq.io_State;
}
SendIO(&tninreq);
}
}
done:
clean("All done");
}
/* Process typed characters */
int
unix_send_tel(buf,n)
char *buf;
int16 n;
{
int i;
for (i=0; (i<n) && (buf[i] != '\r'); i++)
;
if (buf[i] == '\r') {
buf[i] = '\n';
n = i+1;
}
send_tel(buf,n);
}
int
send_tel(buf,n)
char *buf;
int16 n;
{
int i;
tnoutreq.io_Data = buf;
tnoutreq.io_Length = n;
SendIO(&tnoutreq);
i = WaitIO(&tnoutreq);
if (tnoutreq.io_State != old)
{
showstate(old, tnoutreq.io_State);
old = tnoutreq.io_State;
}
}
/* Process incoming TELNET characters */
int
tel_input(tn,bp, len)
register struct telnet *tn;
char *bp;
int len;
{
char c;
int ci;
void doopt(),dontopt(),willopt(),wontopt(),answer();
#ifdef FAST /* DON'T USE -- Aztec memchr() routine is broken */
char *memchr();
/* Optimization for very common special case -- no command chars */
if(tn->state == TS_DATA){
while(bp != NULLBUF && memchr(bp->data,IAC,bp->cnt)
== NULLCHAR){
fflush(stdout);
write(1,bp->data,bp->cnt);
bp = free_mbuf(bp);
}
}
#endif
while(len--){
c = *bp++;
ci = c & 0xff;
switch(tn->state){
case TS_DATA:
if(ci == IAC){
tn->state = TS_IAC;
} else {
if(!tn->remote[TN_TRANSMIT_BINARY])
c &= 0x7f;
putchar(c);
}
break;
case TS_IAC:
switch(ci){
case WILL:
tn->state = TS_WILL;
break;
case WONT:
tn->state = TS_WONT;
break;
case DO:
tn->state = TS_DO;
break;
case DONT:
tn->state = TS_DONT;
break;
case IAC:
putchar(c);
tn->state = TS_DATA;
break;
default:
tn->state = TS_DATA;
break;
}
break;
case TS_WILL:
willopt(tn,ci);
tn->state = TS_DATA;
break;
case TS_WONT:
wontopt(tn,ci);
tn->state = TS_DATA;
break;
case TS_DO:
doopt(tn,ci);
tn->state = TS_DATA;
break;
case TS_DONT:
dontopt(tn,ci);
tn->state = TS_DATA;
break;
}
}
}
#ifdef NOTDEF
/* State change upcall routine */
void
t_state(tcb,old,new)
register struct tcb *tcb;
char old,new;
{
struct telnet *tn;
char notify = 0;
extern char *tcpstates[];
extern char *reasons[];
extern char *unreach[];
extern char *exceed[];
/* Can't add a check for unknown connection here, it would loop
* on a close upcall! We're just careful later on.
*/
tn = (struct telnet *)tcb->user;
if(current != NULLSESSION && current->type == TELNET && current->cb.telnet == tn)
notify = 1;
switch(new){
case CLOSE_WAIT:
if(notify)
printf("%s\r\n",tcpstates[new]);
close_tcp(tcb);
break;
case CLOSED: /* court adjourned */
if(notify){
printf("%s (%s",tcpstates[new],reasons[tcb->reason]);
if(tcb->reason == NETWORK){
switch(tcb->type){
case DEST_UNREACH:
printf(": %s unreachable",unreach[tcb->code]);
break;
case TIME_EXCEED:
printf(": %s time exceeded",exceed[tcb->code]);
break;
}
}
printf(")\r\n");
cmdmode();
}
del_tcp(tcb);
if(tn != NULLTN)
free_telnet(tn);
break;
default:
if(notify)
printf("%s\r\n",tcpstates[new]);
break;
}
fflush(stdout);
}
#endif
/* Delete telnet structure */
static
free_telnet(tn)
struct telnet *tn;
{
if(tn != NULLTN)
free((char *)tn);
}
/* The guts of the actual Telnet protocol: negotiating options */
static
void
willopt(tn,opt)
struct telnet *tn;
int opt;
{
int ack;
void answer();
#ifdef DEBUG
printf("recv: will ");
if(opt <= NOPTIONS)
printf("%s\r\n",t_options[opt]);
else
printf("%u\r\n",opt);
#endif
switch(opt){
case TN_TRANSMIT_BINARY:
case TN_ECHO:
case TN_SUPPRESS_GA:
if(tn->remote[opt] == 1)
return; /* Already set, ignore to prevent loop */
if(opt == TN_ECHO){
if(refuse_echo){
/* User doesn't want to accept */
ack = DONT;
break;
} else
raw(); /* Put tty into raw mode */
}
tn->remote[opt] = 1;
ack = DO;
break;
default:
ack = DONT; /* We don't know what he's offering; refuse */
}
answer(tn,ack,opt);
}
static
void
wontopt(tn,opt)
struct telnet *tn;
int opt;
{
void answer();
#ifdef DEBUG
printf("recv: wont ");
if(opt <= NOPTIONS)
printf("%s\r\n",t_options[opt]);
else
printf("%u\r\n",opt);
#endif
if(opt <= NOPTIONS){
if(tn->remote[opt] == 0)
return; /* Already clear, ignore to prevent loop */
tn->remote[opt] = 0;
if(opt == TN_ECHO)
cooked(); /* Put tty into cooked mode */
}
answer(tn,DONT,opt); /* Must always accept */
}
static
void
doopt(tn,opt)
struct telnet *tn;
int opt;
{
void answer();
int ack;
#ifdef DEBUG
printf("recv: do ");
if(opt <= NOPTIONS)
printf("%s\r\n",t_options[opt]);
else
printf("%u\r\n",opt);
#endif
switch(opt){
#ifdef FUTURE /* Use when local options are implemented */
if(tn->local[opt] == 1)
return; /* Already set, ignore to prevent loop */
tn->local[opt] = 1;
ack = WILL;
break;
#endif
default:
ack = WONT; /* Don't know what it is */
}
answer(tn,ack,opt);
}
static
void
dontopt(tn,opt)
struct telnet *tn;
int opt;
{
void answer();
#ifdef DEBUG
printf("recv: dont ");
if(opt <= NOPTIONS)
printf("%s\r\n",t_options[opt]);
else
printf("%u\r\n",opt);
#endif
if(opt <= NOPTIONS){
if(tn->local[opt] == 0){
/* Already clear, ignore to prevent loop */
return;
}
tn->local[opt] = 0;
}
answer(tn,WONT,opt);
}
static
void
answer(tn,r1,r2)
struct telnet *tn;
int r1,r2;
{
struct mbuf *bp,*qdata();
char s[3];
#ifdef DEBUG
switch(r1){
case WILL:
printf("sent: will ");
break;
case WONT:
printf("sent: wont ");
break;
case DO:
printf("sent: do ");
break;
case DONT:
printf("sent: dont ");
break;
}
if(r2 <= 6)
printf("%s\r\n",t_options[r2]);
else
printf("%u\r\n",r2);
#endif
s[0] = IAC;
s[1] = r1;
s[2] = r2;
tnoutreq.io_Data = s;
tnoutreq.io_Length = 3;
DoIO(&tnoutreq);
/*
bp = qdata(s,(int16)3);
send_tcp(tn->tcb,bp);
*/
}
#define BUFMAXCNT 150
static char conbuf[BUFMAXCNT];
static int concnt = 0;
int
amigaputchar(c)
char c;
{
conbuf[concnt++] = c;
if ((c == '\n') || (concnt == BUFMAXCNT))
amigaflush();
return c;
}
amigaflush()
{
if (concnt == 0)
return;
consout.io_Data = (APTR) conbuf;
consout.io_Length = concnt;
consout.io_Command = CMD_WRITE;
DoIO(&consout);
concnt = 0;
}
/*
* Begin terrible, horrible hack. All output should be printed upon (into?)
* the window we opened before. Here goes nothing...
*/
printf(a, b, c, d, e, f, g, h, i, j, k)
char *a;
int b, c, d, e, f, g, h, i, j, k;
{
if (concnt)
amigaflush();
sprintf(conbuf, a, b, c, d, e, f, g, h, i, j, k);
consout.io_Data = (APTR) conbuf;
consout.io_Length = strlen(conbuf);
consout.io_Command = CMD_WRITE;
DoIO(&consout); /* no use in doing this async */
}